package logic.status;

import java.util.HashMap;
import java.util.Map;

import main.listeners.IListenerContainer;
import networking.messages.syncMessages.ValueType;

public abstract class StatusValueManager<T extends ValueListener> implements IListenerContainer {
	
	protected Map<Float, StatusValueContainer<T>> containers;
	protected StatusValueContainer<T> defaultContainer;
	protected Class<?> listenerClass;
	
	public StatusValueManager(Class<?> listenerClass) {
		this.listenerClass = listenerClass;
		
		containers = new HashMap<Float, StatusValueContainer<T>>();
		defaultContainer = getNewContainer(0f);
		containers.put(Float.valueOf(0f), defaultContainer);
	}
	
	public abstract StatusValueContainer<T> getNewContainer(float diff);
	
	@Override
	public void addListener(Object listener) { addListener(listener, 0f); }
	
	@Override
	public boolean removeListener(Object listener) {
		if(defaultContainer.removeStatusListener(listener)) return  true;
		
		Float diff = null;
		for(Float f : containers.keySet()) {
			if(containers.get(f) == listener) {
				diff = f;
				break;
			}
		}
		
		if(diff != null) return containers.remove(diff) != null;
		return false;
	}
	
	public void addListener(Object listener, float diff) {
		Float delta = Float.valueOf(diff);
		
		StatusValueContainer<T> container = containers.get(delta);
		if(container == null) {
			container = getNewContainer(diff);
			containers.put(delta, container);
		}
		assert(container != null);
		
		container.addStatusListener(listener);
	}
	
	public StatusValueContainer<T> getDefaultContainer() { return defaultContainer; }
	
	public StatusValueContainer<T> getValueContainer(float diff) { return containers.get(Float.valueOf(diff)); }
	
	public float getFloatValue(ValueType type) { return defaultContainer.getFloatValue(type); }
	
	public int getIntValue(ValueType type) { return defaultContainer.getIntValue(type); }
	
	public void changeValue(ValueType type, int value) {
		for(StatusValueContainer<T> container : containers.values()) {
			container.changeValue(type, value);
		}
	}
	
	public void changeValue(ValueType type, float value) {
		for(StatusValueContainer<T> container : containers.values()) {
			container.changeValue(type, value);
		}
	}
	
	public void cleanup() {
		defaultContainer.cleanup();
		for(StatusValueContainer<T> container : containers.values()) {
			container.cleanup();
		}
		containers.clear();
	}
}